package com.taomus.mytools.lang.jruby;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.SequenceInputStream;
import java.io.UnsupportedEncodingException;

import org.jruby.Ruby;
import org.jruby.RubyRuntimeAdapter;
import org.jruby.javasupport.JavaEmbedUtils;
import org.jruby.runtime.builtin.IRubyObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.taomus.mytools.lang.inter.IInvoke;
import com.taomus.mytools.lang.inter.IMethod;


public class JRubyMethod implements IMethod {

	private Ruby runtime;
	private RubyRuntimeAdapter evaler;
	private InputStream input;
	private String filename;
	private String objName;

	public JRubyMethod(String name, Ruby runtime, RubyRuntimeAdapter evaler,
			InputStream input, String filename) {
		super();
		this.runtime = runtime;
		this.evaler = evaler;
		this.input = input;
		this.filename = filename;
		this.objName = name;

	}

	@Override
	public IInvoke getMethod(String name) {
		return new JRubyInvoke(this.objName,this.runtime,this.evaler,this.input,this.filename,name);
	}

	public static class JRubyInvoke implements IInvoke {
		private static Logger logger = LoggerFactory.getLogger(IInvoke.class);
		private String method;
		private Ruby runtime;
		
		private RubyRuntimeAdapter evaler;
		private InputStream input;
		private String filename;
		private String objName;
		private String funName;
		
		public JRubyInvoke(String name, Ruby runtime, RubyRuntimeAdapter evaler,
				InputStream input, String filename,String funName) {
			this.funName = funName;
			this.runtime = runtime;
			this.evaler = evaler;
			this.input = input;
			this.filename = filename;
			this.objName = name;
		}

		@Override
		public Object invoke() {
			return this.invoke(new Object[]{null});
		}

		@Override
		public Object invoke(Object... args) {
			logger.debug("invoke " + method);
			IRubyObject rubyObject = null;
			String script = this.sourceCode(this.funName,args.length);
			InputStream input2 = null;
			try {
				input2 = new ByteArrayInputStream(script.getBytes("utf-8"));
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
			this.input = new SequenceInputStream(this.input,input2);
			rubyObject = evaler.parse(runtime, this.input, filename, 1).run();
			
			return JavaEmbedUtils.invokeMethod(runtime, rubyObject, "jrubyinstance",
					args, Object.class);
		}
		
		private String sourceCode(String name,int argNum) {
			StringBuffer argString = new StringBuffer();
			if(argNum==1){
				argString.append("arg0");
			}else if(argNum>1){
				argString.append("arg0");
				for(int i=1;i<argNum;i++){
					argString.append(",");
					argString.append("arg"+i);
				}
			}
			StringBuffer sb = new StringBuffer();
			sb.append("\ndef jrubyinstance(");
			sb.append(argString.toString());
			sb.append(")\n	a = ");
			sb.append(objName);
			sb.append(".new\n	a.");
			sb.append(name);
			sb.append("(");
			sb.append(argString.toString());
			sb.append(")\nend");
			return sb.toString();
		}
	}
}
